/* $Header: scc_init.c,v 2.2 01/10/02 10:33:02 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:  scc_init.c                                            */
/* ============                                                        */
/*                                                                     */
/* Author:  Lesley Freed                                               */
/*                                                                     */
/* MODULE PURPOSE:  To provide utilities for initializing the SCC      */
/*                  (single column compensation) or test plot control  */
/*                  variables.                                         */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <ramps.h>
#include <zone_config.h>
#include <i_op.h>
#include <zone_status.h>
#include <status.h>
#include <error.h>
#include <sig_types.h>
#include <sigpath.h>
#include <run_ui.h>
#include <clock_ui.h>
#include <p_status.h>
#include <det_ui.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/


/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/


/***********************************************************************/
/* FUNCTION:  InitializeScc                                            */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To initialize data structs for single column compensation.*/
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED: Ccomp1, Ccomp2: working values for SCC                */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

void InitializeScc( void )
{
   /* Set up pointers to column compensation status and profiles */
   Ccomp1.pdata      = &Ccomp1_Data;
   Ccomp2.pdata      = &Ccomp2_Data;
   Test_Plot.pdata   = &Test_Plot_Data;
   Test_Signal.pdata = &Test_Signal_Data;

   Ccomp1.pprofile    = ( PROFILE * )Ccomp1_Profile;
   Ccomp2.pprofile    = ( PROFILE * )Ccomp2_Profile;

   Test_Plot.pprofile   = ( PROFILE * )TEST_PLOT_PROFILE;
   Test_Signal.pprofile = ( PROFILE * )TEST_SIG_PROFILE;

   /* Set up initial values for the scc compensation   */
   Ccomp1.value            = 0;
   Ccomp1.segment_count    = 0;
   Ccomp1.subsegment_count = 0;
   Ccomp1.signal_count     = NO_OF_SIGNALS_PER_SUBSEGMENT;
   Ccomp1.type             = CCOMP1_TYPE;
   Ccomp1.scale_factor     = COL_COMP_SCALE_FACTOR;

   Ccomp2.value            = 0;
   Ccomp2.segment_count    = 0;
   Ccomp2.subsegment_count = 0;
   Ccomp2.signal_count     = NO_OF_SIGNALS_PER_SUBSEGMENT;
   Ccomp2.type             = CCOMP2_TYPE;
   Ccomp2.scale_factor     = COL_COMP_SCALE_FACTOR;

   /* Set up initial values for the test plot          */
   Test_Plot.value            = 0;
   Test_Plot.type             = TEST_PLOT_TYPE;
   Test_Plot.segment_count    = 0;
   Test_Plot.subsegment_count = 0;
   Test_Plot.signal_count     = NO_OF_SIGNALS_PER_SUBSEGMENT;
   Test_Plot.pdata->Nstd      = 15;
   Test_Plot.pdata->Mstd      = 5;
   Test_Plot.pdata->Nlast     = 0;
   Test_Plot.pdata->Mlast     = 0;
   Test_Plot.scale_factor     = INIT_TEST_PLOT_SCALE_FACTOR;

   /* Set up initial values for the test signal        */
   Test_Signal.value            = 0;
   Test_Signal.type             = TEST_SIGNAL_TYPE;
   Test_Signal.segment_count    = 0;
   Test_Signal.subsegment_count = 0;
   Test_Signal.signal_count     = NO_OF_SIGNALS_PER_SUBSEGMENT;
   Test_Signal.pdata->Nstd      = 60;
   Test_Signal.pdata->Mstd      = 20;
   Test_Signal.pdata->Nlast     = 0;
   Test_Signal.pdata->Mlast     = 0;
   Test_Signal.scale_factor     = COL_COMP_SCALE_FACTOR;

   /* Set the state of scc compensation to initial conditions */
   Scc_Run_State = NOT_IN_RUN;
   Scc_Start_Pending = FALSE;
}



/***********************************************************************/
/* FUNCTION:  StartBlankRun                                            */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To initialize the control variables for collecting an     */
/*           SCC profile.                                              */
/*                                                                     */
/* PARAMETERS:  ccomp = signal(s) to perform blank run on              */
/*              local = TRUE if initiated by keyboard or timed event   */
/*                      FALSE if initiated by datacomm                 */
/*                                                                     */
/* RETURNED VALUE:  UI_ERR type error code                             */
/*                                                                     */
/* GLOBALS USED:  Run_State, Active_Wkfile                             */
/*                                                                     */
/* CALLS:  SccPreRun                                                   */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

UI_ERR StartBlankRun( CCOMP ccomp, INT32 local )
{
   POSITION ccomp1_position;
   POSITION ccomp2_position;

   /* First, see if we have valid detector position setpt(s) and that the    */
   /* detector is ON.  If there are no detectors installed the               */
   /* detector position setpt will be NULL_POSITION                          */

   ccomp1_position = Active_Wkfile.col_comp1_det;
   ccomp2_position = Active_Wkfile.col_comp2_det;

   switch ( ccomp )
   {
      case CCOMP1_2:
         if ( ccomp2_position == NULL_POSITION ) return SCC2_DET_SETPT;
         if ( !DetectorIsOn(ccomp2_position) )
         {
            return ( ccomp2_position == FRONT ) ? FRONT_DET_OFF : BACK_DET_OFF;
         }
         /* fall through to CCOMP1 case */
      case CCOMP1:
         if ( ccomp1_position == NULL_POSITION ) return SCC1_DET_SETPT;
         if ( !DetectorIsOn(ccomp1_position) )
         {
            return ( ccomp1_position == FRONT ) ? FRONT_DET_OFF : BACK_DET_OFF;
         }
         break;
      case CCOMP2:
         if ( ccomp2_position == NULL_POSITION ) return SCC2_DET_SETPT;
         if ( !DetectorIsOn(ccomp2_position) )
         {
            return ( ccomp2_position == FRONT ) ? FRONT_DET_OFF : BACK_DET_OFF;
         }
         break;
   }

   /* Next find the run length.  Since we will be doing our calculations in  */
   /* 100ths of a minute, we will convert from milliseconds to .01 minutes.  */
   /* If the run is less than 10 seconds long then we cannot take a profile. */
   /* In this case we will return without doing a compensation run with an   */
   /* error code indicating why no profile was collected.                    */

/* REVISIT: subtract SLACK_TIME to give me some slack, slack is a SMALL number*/
   if ( ( ( Run_Length - SLACK_TIME )/600 ) < MIN_SCC_RUN_TIME-1 )
   {
      return( SCC_RUN_LENGTH_TOO_SHORT );
   }

   /* Use interrupt protection to lock out anything else from starting a run */
   INTERRUPTS_OFF

   if ( (Run_State == RUN_IDLE) || (Run_State == PRE_RUN) )
   {
      if ( Controlled_By_Host && local )
      {
#if 0
         /* this was a local request in INET mode, so notify Maverick */
         DoMVKC((INT32)ccomp);
#endif
      }
      else
      {
         /* initiate a blank run */
         switch ( ccomp )
         {
            case CCOMP1_2:
               /* Enable SCC collect. */
               Ccomp2.collect_scc_flag = 1;
               /* fall through to CCOMP1 case */

            case CCOMP1:
               /* Enable SCC collect. */
               Ccomp1.collect_scc_flag = 1;
               break;

            case CCOMP2:
               /* Enable SCC collect. */
               Ccomp2.collect_scc_flag = 1;
               break;
         }
         SccPreRun();
      }

      INTERRUPTS_ON
      return( OK );
   }
   else
   {
      INTERRUPTS_ON
      return( NOT_VALID_DURING_RUN );
   }
}

/***********************************************************************/
/* FUNCTION:  InitializeSccRun                                         */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To determine which column compensation profiles have been */
/*           selected for collection and initializing those selected.  */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Ccomp1 and/or Ccomp2                                 */
/*                                                                     */
/* CALLS:  InitializeProfile                                           */
/*                                                                     */
/* LIMITATIONS:  This function runs without interrupt protection.      */
/*                                                                     */
/***********************************************************************/

void InitializeSccRun( void )
{
   if ( Ccomp1.collect_scc_flag )
   {
      InitializeProfile( &Ccomp1 );
   }

   if ( Ccomp2.collect_scc_flag )
   {
      InitializeProfile( &Ccomp2 );
   }

}

/***********************************************************************/
/* FUNCTION:  InitializeProfile                                        */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To set up the state variables for collection of an SCC    */
/*           profile                                                   */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Ccomp1, Ccomp1_Data and/or Ccomp2, Ccomp2_Data,      */
/*                Run_Length                                           */
/*                                                                     */
/* CALLS:  none                                                        */
/*                                                                     */
/* LIMITATIONS:  This function runs without interrupt protection.      */
/*                                                                     */
/***********************************************************************/


void InitializeProfile( pCCOMP_TABLE pccomp )
{

   U_INT32  run_length;
   POSITION det_position;

   /* Calculate the number of data points per segment.  First find the run   */
   /* length. Since we will be doing our calculations in 100ths of a minute, */
   /* we will convert from milliseconds to .01 minutes.                      */

/* REVISIT: subtract SLACK_TIME to give me some slack */
   run_length = ( Run_Length - SLACK_TIME )/600;

   pccomp->pdata->Nstd  = ( ( run_length * 60/NO_OF_SIGNALS_PER_SUBSEGMENT )
                            /100 ) * NO_OF_SIGNALS_PER_SUBSEGMENT;

   pccomp->pdata->Nlast = ( ( run_length * 60/NO_OF_SIGNALS_PER_SUBSEGMENT )
                            % 100 ) * NO_OF_SIGNALS_PER_SUBSEGMENT;

   /* Now calculate the number of subsegments between interpolation pts.     */
   /* The second derivative calculation will be done once every subsegment   */

   pccomp->pdata->Mstd  = pccomp->pdata->Nstd/NO_OF_SIGNALS_PER_SUBSEGMENT;
   pccomp->pdata->Mlast = pccomp->pdata->Nlast/NO_OF_SIGNALS_PER_SUBSEGMENT;

   /* Initialize counters */

   pccomp->segment_count = 0;
   pccomp->subsegment_count = 0;
   pccomp->signal_count = NO_OF_SIGNALS_PER_SUBSEGMENT;

   /* Set the detector position stored and the date-time of the collection */
   det_position = ( pccomp == pCCOMP1 ) ? \
                      Active_Wkfile.col_comp1_det : Active_Wkfile.col_comp2_det;

   pccomp->pdata->det_data_stored = det_position;
   pccomp->pdata->det_type        = GetDetectorType( det_position );

   SetDateTime( &(pccomp->pdata->datetime) );

   /* Set data state to INCOMPLETE_DATA.  We are wiping out any  */
   /* previous data.                                             */
   pccomp->pdata->data_valid_flag = INCOMPLETE_DATA;

}



/***********************************************************************/
/* FUNCTION:  StopBlankRun                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To clean up the scc state(s) after a blank run.           */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Ccomp1, Ccomp2:  data struct.s for column comp 1 & 2 */
/*                                                                     */
/* CALLS:  StopScc                                                     */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

void StopBlankRun( void )
{
   if ( Ccomp1.collect_scc_flag == 1 )
   {
      Ccomp1.collect_scc_flag = 0;  /* Reset flag requesting scc collection */
      if ( Ccomp1_Data.data_valid_flag != DATA_OK )
      {
         Ccomp1_Data.data_valid_flag = NO_DATA;
      }
      StopScc( &Ccomp1 );
   }

   if ( Ccomp2.collect_scc_flag == 1 )
   {
      Ccomp2.collect_scc_flag = 0;
      if ( Ccomp2_Data.data_valid_flag != DATA_OK )
      {
         Ccomp2_Data.data_valid_flag = NO_DATA;
      }
      StopScc( &Ccomp2 );
   }
}



/***********************************************************************/
/* FUNCTION:  StopRunForScc                                            */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To change the scc run state to request that the scc       */
/*           signals be reset to their initial values.                 */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Scc_Run_State                                        */
/*                                                                     */
/* CALLS: none                                                         */
/*                                                                     */
/***********************************************************************/

void StopRunForScc( void )
{

   /* Set the scc run state to request that the run be stopped */
   Scc_Run_State = STOP_PENDING;

}


/***********************************************************************/
/* FUNCTION:  ResetScc                                                 */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To initialize the counters and pointers for applying scc. */
/*           This function is called by ServiceCompressedSignals when  */
/*           the run is over.                                          */
/*                                                                     */
/* RETURNED VALUE:  none                                               */
/*                                                                     */
/* GLOBALS USED:  Ccomp1, Ccomp2:  working values for scc profiles 1,2 */
/*                                                                     */
/* CALLS: none                                                         */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

#pragma SECTION PROG=SysCode

void ResetScc( void )
{
   Test_Plot.scale_factor = INIT_TEST_PLOT_SCALE_FACTOR;
   Test_Plot.pprofile = ( PROFILE * )TEST_PLOT_PROFILE;

   StopScc( &Ccomp1 );
   StopScc( &Ccomp2 );
   StopScc( &Test_Plot );
   StopScc( &Test_Signal );
}

#pragma SECTION UNDO



/***********************************************************************/
/* FUNCTION:  StopScc                                                  */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To reset the SCC state variables to the beginning of the  */
/*           profile.                                                  */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

void StopScc( pCCOMP_TABLE pccomp )
{
   /* Reset the counters to the beginning of the profile */

   pccomp->segment_count    = 0;
   pccomp->subsegment_count = 0;
   pccomp->signal_count     = NO_OF_SIGNALS_PER_SUBSEGMENT;

   /* Set the baseline, slope and 2nd derivative to initial values */

   pccomp->value      = 0;
   pccomp->slope      = 0;
   pccomp->deriv2     = 0;

}
